https://rstudio.github.io/leaflet/
Interactive panning/zooming
Notice the icons, when clicked, display the crime description and time when it was committed/reported
| Case Number | Date | Primary Type | Description |
|---|---|---|---|
| HY189866 | 03/18/2015 07:44:00 PM | BATTERY | AGGRAVATED: HANDGUN |
| HY190059 | 03/18/2015 11:00:00 PM | OTHER OFFENSE | PAROLE VIOLATION |
| HY190052 | 03/18/2015 10:45:00 PM | BATTERY | DOMESTIC BATTERY SIMPLE |
| HY190054 | 03/18/2015 10:30:00 PM | BATTERY | SIMPLE |
| HY189976 | 03/18/2015 09:00:00 PM | ROBBERY | ARMED: HANDGUN |
| HY190032 | 03/18/2015 10:00:00 PM | BATTERY | SIMPLE |
| HY190047 | 03/18/2015 11:00:00 PM | BATTERY | DOMESTIC BATTERY SIMPLE |
| HY189988 | 03/18/2015 09:35:00 PM | BATTERY | DOMESTIC BATTERY SIMPLE |
| HY190020 | 03/18/2015 10:09:00 PM | NARCOTICS | POSS: CANNABIS 30GMS OR LESS |
| HY189964 | 03/18/2015 09:25:00 PM | BATTERY | SIMPLE |
| HY189984 | 03/18/2015 09:30:00 PM | CRIMINAL DAMAGE | TO VEHICLE |
| HY189719 | 03/15/2015 04:10:00 PM | OTHER OFFENSE | HARASSMENT BY TELEPHONE |
| HY189966 | 03/18/2015 09:14:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY190056 | 03/18/2015 10:50:00 PM | BATTERY | SIMPLE |
| HY190019 | 03/18/2015 10:31:00 PM | THEFT | RETAIL THEFT |
| HY189725 | 03/18/2015 12:55:00 PM | BURGLARY | FORCIBLE ENTRY |
| HY190071 | 03/18/2015 08:00:00 PM | MOTOR VEHICLE THEFT | AUTOMOBILE |
| HY190036 | 03/18/2015 09:00:00 PM | THEFT | FROM BUILDING |
| HY190063 | 03/18/2015 10:56:00 PM | PUBLIC PEACE VIOLATION | RECKLESS CONDUCT |
| HY190068 | 03/18/2015 10:45:00 PM | THEFT | FROM BUILDING |
| Case Number | Date | Primary Type | Description |
|---|---|---|---|
| HY134412 | 01/30/2015 04:57:39 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY190274 | 03/18/2015 01:00:00 PM | ROBBERY | ARMED: HANDGUN |
| HY189866 | 03/18/2015 07:44:00 PM | BATTERY | AGGRAVATED: HANDGUN |
| HY189976 | 03/18/2015 09:00:00 PM | ROBBERY | ARMED: HANDGUN |
| HY189966 | 03/18/2015 09:14:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY189969 | 03/18/2015 09:44:00 PM | WEAPONS VIOLATION | UNLAWFUL USE HANDGUN |
| HY190003 | 03/18/2015 09:59:00 PM | BATTERY | AGGRAVATED: HANDGUN |
| HY190043 | 03/18/2015 11:00:00 PM | BATTERY | AGGRAVATED: HANDGUN |
| HY190067 | 03/18/2015 11:20:00 PM | BATTERY | AGGRAVATED: HANDGUN |
| HY191604 | 03/18/2015 12:50:00 PM | ASSAULT | AGGRAVATED: HANDGUN |
| HY190586 | 03/19/2015 01:10:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY190103 | 03/19/2015 01:50:00 AM | ROBBERY | ARMED: HANDGUN |
| HY190658 | 03/19/2015 02:26:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY190920 | 03/19/2015 04:09:00 PM | OTHER OFFENSE | GUN OFFENDER: ANNUAL REGISTRATION |
| HY190959 | 03/19/2015 05:43:00 PM | ASSAULT | AGGRAVATED: HANDGUN |
| HY190962 | 03/19/2015 05:52:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY191027 | 03/19/2015 06:40:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY191010 | 03/19/2015 06:45:00 PM | ROBBERY | ARMED: HANDGUN |
| HY191030 | 03/19/2015 07:01:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY191116 | 03/19/2015 07:37:00 PM | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| Case Number | Date | Arrest | Primary Type | Description |
|---|---|---|---|---|
| HY123079 | 01/20/2015 06:10:00 PM | TRUE | NARCOTICS | FORFEIT PROPERTY |
| HY133401 | 01/29/2015 06:16:44 PM | TRUE | NARCOTICS | POSS: CRACK |
| HY134412 | 01/30/2015 04:57:39 PM | TRUE | WEAPONS VIOLATION | UNLAWFUL POSS OF HANDGUN |
| HY133975 | 01/30/2015 11:50:18 AM | TRUE | NARCOTICS | POSS: CRACK |
| HY138419 | 02/03/2015 03:38:00 PM | TRUE | NARCOTICS | MANU/DELIVER: HEROIN (WHITE) |
| HY138450 | 02/03/2015 04:00:00 PM | TRUE | NARCOTICS | MANU/DELIVER: HEROIN (WHITE) |
| HY139499 | 02/04/2015 11:55:21 AM | TRUE | NARCOTICS | POSS: CANNABIS 30GMS OR LESS |
| HY190480 | 02/19/2015 01:30:00 PM | TRUE | THEFT | RETAIL THEFT |
| HY157138 | 02/19/2015 05:36:00 PM | TRUE | NARCOTICS | MANU/DELIVER: HEROIN (WHITE) |
| HY172764 | 03/05/2015 01:40:00 PM | TRUE | NARCOTICS | MANU/DELIVER: HEROIN (WHITE) |
| HY172795 | 03/05/2015 01:41:00 PM | TRUE | NARCOTICS | MANU/DELIVER: HEROIN (WHITE) |
| HY172353 | 03/05/2015 06:35:00 AM | TRUE | NARCOTICS | CRIMINAL DRUG CONSPIRACY |
| HY174264 | 03/06/2015 01:40:00 PM | TRUE | NARCOTICS | MANU/DELIVER:CRACK |
| HY173967 | 03/06/2015 01:50:00 PM | TRUE | NARCOTICS | MANU/DEL:CANNABIS 10GM OR LESS |
| HY174332 | 03/06/2015 05:38:00 PM | TRUE | NARCOTICS | MANU/DELIVER:CRACK |
| HY174440 | 03/06/2015 07:04:00 PM | TRUE | NARCOTICS | POSS: HEROIN(WHITE) |
| HY174329 | 03/06/2015 12:38:00 PM | TRUE | NARCOTICS | POSS: CANNABIS 30GMS OR LESS |
| HY175365 | 03/07/2015 04:00:00 PM | TRUE | NARCOTICS | MANU/DEL:CANNABIS 10GM OR LESS |
| HY191612 | 03/09/2015 09:00:00 AM | TRUE | BATTERY | SIMPLE |
| HY179885 | 03/11/2015 09:15:00 AM | TRUE | OTHER OFFENSE | LICENSE VIOLATION |
---
title: "Chicago Crime Dashboard"
author: "Zack Larsen"
date: "May 18, 2019"
output:
flexdashboard::flex_dashboard:
social: [ "twitter", "facebook", "menu" ]
navbar:
- { title: "About Me", href: "https://zacklarsen.github.io/" }
- { icon: "fa-github", href: "https://github.com/ZackLarsen", align: right}
- { icon: "fa-linkedin", href: "https://www.linkedin.com/in/larsenzachary/", align: right}
source: embed
---
```{r setup, include=FALSE}
library(pacman)
library(tidyverse)
library(shiny)
p_load(flexdashboard, leaflet, leaflet.extras, ggvis, here, conflicted, data.table, jsonlite, kableExtra, glue, geosphere, DT, networkD3, htmltools, geojsonio, magrittr, treemap, highcharter, viridisLite, ggmap)
conflict_prefer("filter", "dplyr")
here::here() # "/Users/zacklarsen/Zack_Master/Projects/Dataviz/R/Divvy_Flex"
stations <- fromJSON("https://feeds.divvybikes.com/stations/stations.json")
crimes <- fread(here("data","Crimes_sample.csv")) %>%
na.omit()
ward_boundaries <- geojsonio::geojson_read(here("data","Boundaries_Wards.geojson"), what = "sp")
```
Landing Page - Crime Map
=========================================
Column
-------------------------------------
### Crimes, plotted using leaflet. This map can be zoomed in on interactively and the station names will be displayed upon clicking the icon.
```{r, cache=TRUE}
crimes_popup <- crimes %>%
mutate(
popup_text = paste(
sep = "
",
glue("{`Primary Type`}"),
Description,
Date,
paste(Latitude, Longitude, sep=', ')
)
) %>%
na.omit()
my_map <- leaflet(crimes_popup) %>%
addTiles() %>%
addMarkers(lat = crimes_popup$Latitude,
lng = crimes_popup$Longitude,
label = lapply(crimes_popup$popup_text, HTML)
)
my_map
```
***
https://rstudio.github.io/leaflet/
- Interactive panning/zooming
- Notice the icons, when clicked, display the crime description and time when it was committed/reported
Column {.tabset}
-------------------------------------
### Data
```{r, cache=TRUE}
crimes %>%
select(`Case Number`, Date, `Primary Type`, Description) %>%
head(n=20) %>%
kable() %>%
kable_styling()
```
### Crimes Involving Use of Firearm
```{r, cache=TRUE, eval=TRUE}
crimes %>%
filter(grepl("GUN",Description)) %>%
select(`Case Number`, Date, `Primary Type`, Description) %>%
arrange(Date) %>%
head(n=20) %>%
kable() %>%
kable_styling()
```
### Arrests Made
```{r, cache=TRUE, eval=TRUE}
crimes %>%
filter(Arrest == TRUE) %>%
select(`Case Number`, Date, Arrest, `Primary Type`, Description) %>%
arrange(Date) %>%
head(n=20) %>%
kable() %>%
kable_styling()
```
Crime Features {.storyboard}
=========================================
### Treemap
```{r, cache=TRUE, eval=TRUE}
thm <-
hc_theme(
colors = c("#1a6ecc", "#434348", "#90ed7d"),
chart = list(
backgroundColor = "transparent",
style = list(fontFamily = "Source Sans Pro")
),
xAxis = list(
gridLineWidth = 1
)
)
treemap_data <- crimes %>%
select(`Case Number`, `Primary Type`, Description) %>%
group_by(`Primary Type`, Description) %>%
summarise(Count = n_distinct(`Case Number`))
tm <- treemap(treemap_data, index = c("Primary Type", "Description"),
vSize = "Count", vColor = "Count",
type = "value", palette = rev(viridis(6)))
highchart() %>%
hc_add_series_treemap(tm, allowDrillToNode = TRUE,
layoutAlgorithm = "squarified") %>%
hc_add_theme(thm)
```
### Heatmap
```{r, cache=TRUE, eval=TRUE}
leaflet(crimes) %>%
addTiles() %>%
addHeatmap(lng=~Longitude,
lat=~Latitude,
radius = 8)
```
### Circle Layers
```{r, cache=TRUE, eval=TRUE}
BATTERY <- crimes[crimes$`Primary Type` == 'BATTERY',]
ROBBERY <- crimes[crimes$`Primary Type` == 'ROBBERY',]
HOMICIDE <- crimes[crimes$`Primary Type` == 'HOMICIDE',]
ASSAULT <- crimes[crimes$`Primary Type` == 'ASSAULT',]
PROSTITUTION <- crimes[crimes$`Primary Type` == 'PROSTITUTION',]
GTA <- crimes[crimes$`Primary Type` == 'MOTOR VEHICLE THEFT',]
leaflet(crimes) %>%
# Base groups
addTiles(group = "Default") %>%
# Overlay groups
addCircles(~BATTERY$Longitude, ~BATTERY$Latitude, group = "BATTERY") %>%
addCircles(~ROBBERY$Longitude, ~ROBBERY$Latitude, group = "ROBBERY") %>%
addCircles(~HOMICIDE$Longitude, ~HOMICIDE$Latitude, group = "HOMICIDE") %>%
addCircles(~ASSAULT$Longitude, ~ASSAULT$Latitude, group = "ASSAULT") %>%
addCircles(~PROSTITUTION$Longitude, ~PROSTITUTION$Latitude, group = "PROSTITUTION") %>%
addCircles(~GTA$Longitude, ~GTA$Latitude, group = "GTA") %>%
# Layers control
addLayersControl(
overlayGroups = c("BATTERY","ROBBERY","HOMICIDE","ASSAULT","PROSTITUTION","GTA"),
options = layersControlOptions(collapsed = FALSE)
)
```
Ward Features {.storyboard}
=========================================
### Crime Totals By Ward
```{r, cache=TRUE, eval=TRUE}
ward_totals <- crimes %>%
select(Ward, `Primary Type`) %>%
group_by(Ward) %>%
summarise(n()) %<>%
mutate(count = `n()`)
ward_totals <- setNames(ward_totals$count, as.character(ward_totals$Ward))
ward_boundaries$crime_total <- ward_totals
labels <- sprintf(
"Ward #%s
%g crimes committed in this ward",
ward_boundaries$ward, ward_boundaries$crime_total
) %>% lapply(htmltools::HTML)
qpal <- colorQuantile("Reds", ward_boundaries$crime_total, n = 10)
leaflet(ward_boundaries) %>%
addTiles() %>%
addPolygons(fillColor = ~qpal(crime_total),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.9,
highlight = highlightOptions(
weight = 3, # This is the width of the dashed line
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
label = ~labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addLegend(pal = qpal,
values = ~crime_total,
opacity = 0.7,
title = "Crime Count Quantile",
position = "topright")
```
### Layer Selection By Crime Type
```{r, cache=TRUE, eval=FALSE}
ward_totals_by_type <- crimes %>%
select(Ward, `Primary Type`) %>%
group_by(Ward, `Primary Type`) %>%
summarise(n()) %<>%
rename(count = `n()`) %>%
tidyr::spread(key = `Primary Type`,value = count)
ward_totals_by_type[is.na(ward_totals_by_type)] <- 0
battery_totals <- setNames(ward_totals_by_type$BATTERY, as.character(ward_totals_by_type$Ward))
robbery_totals <- setNames(ward_totals_by_type$ROBBERY, as.character(ward_totals_by_type$Ward))
ward_boundaries$battery_total <- battery_totals
ward_boundaries$robbery_total <- robbery_totals
get_palette <- function(category){
colorQuantile("Reds", ward_boundaries$category, n = 10)
}
leaflet(ward_boundaries) %>%
addTiles() %>%
addPolygons(fillColor = ~get_palette(battery_totals),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.9,
group = "BATTERY",
highlight = highlightOptions(
weight = 5,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE)) %>%
addPolygons(fillColor = ~get_palette(robbery_totals),
weight = 2,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.9,
group = "ROBBERY",
highlight = highlightOptions(
weight = 5,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE)) %>%
addLayersControl(
overlayGroups = c("BATTERY","ROBBERY"),
options = layersControlOptions(collapsed = FALSE)
)
```